module sdldee.rwops;

import std.c.stdio;
import std.stdio;
import std.string;

import sdldee.c.sdl;
import sdldee.exception;

enum Seek {
	SET = 0,
	CURRENT = 1,
	END = 2
}

class UnableToCreateRwopsException : SdlException {
	this() {
		super("Unable to create Rwops!");
	}
}

class Rwops {
	private SDL_RWops* _rwops;
	debug {
		static private int idcount = 0;
		private int id;
	}
	
	this(SDL_RWops* rwops) {
		debug {
			writefln("Creating Rwops from SDL_RWops pointer");
			id = idcount++;
			writefln("Id of Rwops object: %d", id);
			writefln("Address of SDL_RWops: %x", rwops);
			writefln();
		}
		
		_rwops = rwops;
	}
	
	this(char[] filename, char[] mode) {
		debug {
			writefln("Creating Rwops from file");
			writefln("Filename: %s", filename);
			writefln("Mode: %s", mode);
		}
		
		if((_rwops = SDL_RWFromFile(toStringz(filename), toStringz(mode))) == null)
			throw new UnableToCreateRwopsException();
		
		debug {
			id = idcount++;
			writefln("Id of Rwops object: %d", id);
			writefln("Address of SDL_RWops: %x", _rwops);
			writefln();
		}
	}
	
	/* FIXME: This doesn't link properly
	this(FILE * fp, bool autoclose) {
		debug {
			writefln("Creating Rwops from file pointer:");
			writefln("File pointer: %x", fp);
			writefln("Autoclose: %s", autoclose);
		}
		
		if((_rwops = SDL_RWFromFP(fp, autoclose)) == null)
			throw new UnableToCreateRwopsException();
		
		
	}*/
	
	this(void* mem, int size) {
		if((_rwops = SDL_RWFromMem(mem, size)) == null)
			throw new UnableToCreateRwopsException();
	}
	
	~this() {
		debug {
			writefln("Deleting Rwops object, closing SDL_RWops");
			writefln("Id of Rwops object: %d", id);
			writefln("Address of SDL_Rwops: %x", _rwops);
			writefln();
		}
		
		_rwops.close(_rwops);
	}
	
	public SDL_RWops* crwops() {
		return _rwops;
	}
	
	public int seek(int offset, Seek seek) {
		return _rwops.seek(_rwops, offset, seek);
	}
	
	public int read(void* ptr, int size, int maxnum) {
		return _rwops.read(_rwops, ptr, size, maxnum);
	}
	
	public bool write(void* ptr, int size, int num) {
		return _rwops.write(_rwops, ptr, size, num) == num;
	}
	
	public ushort readLE16() {
		return SDL_ReadLE16(_rwops);
	}
	
	public ushort readBE16() {
		return SDL_ReadBE16(_rwops);
	}
	
	public uint readLE32() {
		return SDL_ReadLE32(_rwops);
	}
	
	public uint readBE32() {
		return SDL_ReadLE32(_rwops);
	}
	
	public ulong readLE64() {
		return SDL_ReadLE64(_rwops);
	}
	
	public ulong readBE64() {
		return SDL_ReadLE64(_rwops);
	}

	public int writeLE16(ushort value) {
		return SDL_WriteLE16(_rwops, value);
	}
	
	public int writeBE16(ushort value) {
		return SDL_WriteBE16(_rwops, value);
	}
	
	public int writeLE32(uint value) {
		return SDL_WriteLE32(_rwops, value);
	}
	
	public int writeBE32(uint value) {
		return SDL_WriteBE32(_rwops, value);
	}
	
	public int writeLE64(ulong value) {
		return SDL_WriteLE64(_rwops, value);
	}
	
	public int writeBE64(ulong value) {
		return SDL_WriteBE64(_rwops, value);
	}
}
